﻿namespace MicroCloud.AspNetCore.SignalR
{
    #region "SignalR Hub基类"
    /// <summary>
    /// SignalR Hub基类
    /// </summary>
    // [ApiAuthorize]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public abstract class HubBase : Hub
    {
        #region "属性"
        #region "获取 服务提供者"
        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }
        #endregion
        #region "获取 日志记录器"
        /// <summary>
        /// 获取 日志记录器
        /// </summary>
        protected ILogger Logger { get; }
        #endregion
        #region "获取 事件总线"
        /// <summary>
        /// 获取 事件总线
        /// </summary>
        protected IEventBus EventBus { get; }
        #endregion
        #region "获取 通信连接用户缓存"
        /// <summary>
        /// 获取 通信连接用户缓存
        /// </summary>
        protected IConnectionUserCache UserCache { get; }
        #endregion

        #endregion

        #region "构造函数"
        #region "初始化一个 <see cref="HubBase"/> 类型的新实例"
        /// <summary>
        /// 初始化一个 <see cref="HubBase"/> 类型的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        /// <param name="eventBus">事件总线接口</param>
        /// <param name="userCache">SignalR连接用户缓存接口</param>
        protected HubBase(IServiceProvider provider, IEventBus eventBus, IConnectionUserCache userCache)
        {
            ServiceProvider = provider;
            Logger = provider.GetLogger<HubBase>();
            EventBus = eventBus;
            UserCache = userCache;
        }
        #endregion

        #endregion

        #region "方法"
        #region "在与集线器建立新连接时调用"
        /// <summary>
        /// 在与集线器建立新连接时调用
        /// </summary>
        /// <returns>一个<see cref="Task" />表示异步连接的</returns>
        public override async Task OnConnectedAsync()
        {
            HubConnectionEventData eventData = new(Clients, Context, Groups);

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.AddConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }

            await base.OnConnectedAsync();

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogDebug("用户 {userKey}[{connectionId}] 与SignalR集线器建立连接", userKey, Context.ConnectionId);
        }
        #endregion
        #region "当终止与集线器的连接时调用"
        /// <summary>
        /// 当终止与集线器的连接时调用
        /// </summary>
        /// <param name="exception">异常信息</param>
        /// <returns></returns>
        public override async Task OnDisconnectedAsync(System.Exception exception)
        {
            HubDisconnectionEventData eventData = new(Clients, Context, Groups) { Exception = exception };

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.RemoveConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }
            eventData.UserKey = userKey;
            UserCache.RemoveUserGroupByConnection(Context.ConnectionId);

            await base.OnDisconnectedAsync(exception);

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogInformation(exception, $"用户：{userKey}[{Context.ConnectionId}] 与SignalR集线器终止连接");
        }
        #endregion

        //#region "加入组"
        ///// <summary>
        ///// 加入组
        ///// </summary>
        ///// <param name="groupKeys">组标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> AddToGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubAddToGroupEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (var groupKey in groupKeys)
        //    {
        //        await Groups.AddToGroupAsync(Context.ConnectionId, groupKey);
        //        UserCache.AddUserGroup(userKey, groupKey, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR集线器加入组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion
        //#region "离开组"
        ///// <summary>
        ///// 离开组
        ///// </summary>
        ///// <param name="groupKeys">组标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> RemoveFromGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubRemoveFromGroupEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (string groupKey in groupKeys)
        //    {
        //        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupKey);
        //        UserCache.RemoveUserGroup(userKey, groupKey, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR集线器离开组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion

        //#region "发送消息"
        ///// <summary>
        ///// 发送消息
        ///// </summary>
        ///// <param name="dto">SignalR消息DTO</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> Send(MessageDto dto)
        //{
        //    Check.NotNull(dto, nameof(dto));
        //    Check.NotNullOrEmpty(dto.Method, nameof(dto.Method));
        //    Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));
        //    Check.NotNullOrEmpty(dto.Content, nameof(dto.Content));
        //    if (!(dto.ToUsers?.Count > 0) && !(dto.ToGroups?.Count > 0))
        //    {
        //        return new AjaxResult("没有收件人信息", AjaxResultType.Error);
        //    }

        //    HubMessageSendEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }
        //    dto.Sender = userKey.IsMissing() ? Context.ConnectionId : userKey;

        //    var dateTimeNow = DateTime.Now;
        //    var dateTimeIncreaseVal = dateTimeNow.ToString("yyyyMMddHHmmssfff").CastTo<long>(0);
        //    dto.Key = dateTimeIncreaseVal;
        //    dto.CreatedTime = dateTimeNow;

        //    //发送至用户
        //    if (dto.ToUsers?.Count > 0)
        //    {
        //        foreach (var toUser in dto.ToUsers)
        //        {
        //            var user = await UserCache.GetUser(toUser);
        //            if (user?.ConnectionIds.Count > 0)
        //            {
        //                await Clients.Clients(user?.ConnectionIds).SendAsync(dto.Method, dto);
        //            }
        //        }
        //    }
        //    //发送至组
        //    if (dto.ToGroups?.Count > 0)
        //    {
        //        await Clients.Groups(dto.ToGroups).SendAsync(dto.Method, dto);
        //    }

        //    eventData.Dto = dto;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"消息 [Key：{dto.Key}] 发送成功。至用户：{dto.ToUsers.ExpandAndToString()}。至组：{dto.ToGroups.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion
        //#region "延时消息"
        ///// <summary>
        ///// 延时消息
        ///// </summary>
        ///// <param name="dto">SignalR延时消息DTO</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> Delay(MessageDelayDto dto)
        //{
        //    Check.NotNull(dto, nameof(dto));
        //    Check.NotNullOrEmpty(dto.Method, nameof(dto.Method));
        //    Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));
        //    Check.NotNullOrEmpty(dto.Content, nameof(dto.Content));
        //    if (!(dto.ToUsers?.Count > 0) && !(dto.ToGroups?.Count > 0))
        //    {
        //        return new AjaxResult("没有收件人信息", AjaxResultType.Error);
        //    }

        //    HubMessageDelayEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }
        //    dto.Sender = userKey.IsMissing() ? Context.ConnectionId : userKey;

        //    var dateTimeNow = DateTime.Now;
        //    var dateTimeIncreaseVal = dateTimeNow.ToString("yyyyMMddHHmmssfff").CastTo<long>(0);
        //    dto.Key = dateTimeIncreaseVal;
        //    dto.CreatedTime = dateTimeNow;

        //    var criticalDiffMinutes = 10;
        //    var diffTimeSpan = dto.SendTime.Subtract(dateTimeNow);
        //    if (diffTimeSpan.TotalMinutes <= criticalDiffMinutes)
        //    {
        //        Logger.LogInformation($"延时消息 [Key：{dto.Key}] 发送时间 [{dto.SendTime}] 与当前时间 [{dateTimeNow}] 相比小于 {criticalDiffMinutes} 分钟，将修改为立即发送模式。");
        //        dto.SendTime = dateTimeNow;

        //        HubMessageSendEventData eventData2 = new(Clients, Context, Groups);

        //        //发送至用户
        //        if (dto.ToUsers?.Count > 0)
        //        {
        //            foreach (var toUser in dto.ToUsers)
        //            {
        //                var user = await UserCache.GetUser(toUser);
        //                if (user?.ConnectionIds.Count > 0)
        //                {
        //                    await Clients.Clients(user?.ConnectionIds).SendAsync(dto.Method, dto);
        //                }
        //            }
        //        }
        //        //发送至组
        //        if (dto.ToGroups?.Count > 0)
        //        {
        //            await Clients.Groups(dto.ToGroups).SendAsync(dto.Method, dto);
        //        }

        //        eventData2.Dto = new MessageDto(dto.Id, dto.Method, dto.MessageType, dto.ResponseType, dto.Title, dto.Content, dto.Payload, dto.Sender, dto.ToUsers, dto.ToGroups, dto.IsSystem);
        //        //触发事件
        //        await EventBus?.PublishAsync(eventData2);

        //        var msgString = $"消息 [Key：{dto.Key}] 发送成功。至用户：{dto.ToUsers.ExpandAndToString()}。至组：{dto.ToGroups.ExpandAndToString()}。";
        //        Logger.LogInformation(msgString);
        //        return new AjaxResult(msgString, AjaxResultType.Success);
        //    }
        //    else
        //    {
        //        eventData.Dto = dto;
        //        //触发事件
        //        await EventBus?.PublishAsync(eventData);

        //        var msgString = $"延时消息 [Key：{dto.Key}] 预处理成功。请通过后台任务接收延时消息事件数据进行处理。";
        //        Logger.LogInformation(msgString);
        //        return new AjaxResult(msgString, AjaxResultType.Success);
        //    }
        //}
        //#endregion
        //#region "周期消息"
        ///// <summary>
        ///// 周期消息
        ///// </summary>
        ///// <param name="dto">SignalR周期消息DTO</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> Recurrent(MessageRecurrentDto dto)
        //{
        //    Check.NotNull(dto, nameof(dto));
        //    Check.NotNullOrEmpty(dto.Method, nameof(dto.Method));
        //    Check.NotNullOrEmpty(dto.Title, nameof(dto.Title));
        //    Check.NotNullOrEmpty(dto.Content, nameof(dto.Content));
        //    if (!(dto.ToUsers?.Count > 0) && !(dto.ToGroups?.Count > 0))
        //    {
        //        return new AjaxResult("没有收件人信息", AjaxResultType.Error);
        //    }

        //    HubMessageRecurrentEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }
        //    dto.Sender = userKey.IsMissing() ? Context.ConnectionId : userKey;

        //    var dateTimeNow = DateTime.Now;
        //    var dateTimeIncreaseVal = dateTimeNow.ToString("yyyyMMddHHmmssfff").CastTo<long>(0);
        //    dto.Key = dateTimeIncreaseVal;
        //    dto.CreatedTime = dateTimeNow;

        //    if (dto.SendCron.IsMissing())
        //    {
        //        return new AjaxResult("发送类型为周期消息下 {nameof(dto.SendCron)} 不能为空", AjaxResultType.Error);
        //    }
        //    if (!dto.SendCron.IsCronExpression())
        //    {
        //        return new AjaxResult("{nameof(dto.SendCron)} 表达式值无效", AjaxResultType.Error);
        //    }

        //    eventData.Dto = dto;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"周期消息 [Key：{dto.Key}] 预处理成功。请通过后台任务接收周期消息事件数据进行处理。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion

        #endregion

        #region "受保护方法"
        #region "获取当前用户标识"
        /// <summary>
        /// 获取当前用户标识
        /// </summary>
        /// <returns></returns>
        protected string GetCurrentUserKey()
        {
            //获取用户Id信息
            string userKey = Context.User.Identity.GetUserId();
            userKey = userKey.IsMissing() ? KeyConstants.AnonymousUser : userKey;
            return userKey;
        }
        #endregion

        #endregion

    }
    #endregion

    #region "支持强类型的SignalR Hub基类"
    /// <summary>
    /// 支持强类型的SignalR Hub基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public abstract class HubBase<T> : Hub<T>
        where T : class
    {
        #region "属性"
        #region "获取 服务提供者"
        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }
        #endregion
        #region "获取 日志记录器"
        /// <summary>
        /// 获取 日志记录器
        /// </summary>
        protected ILogger Logger { get; }
        #endregion
        #region "获取 通信连接用户缓存"
        /// <summary>
        /// 获取 通信连接用户缓存
        /// </summary>
        protected IConnectionUserCache UserCache { get; }
        #endregion
        #region "获取 事件总线"
        /// <summary>
        /// 获取 事件总线
        /// </summary>
        protected IEventBus EventBus { get; }
        #endregion

        #endregion

        #region "构造函数"
        #region "初始化一个支持强类型的SignalR Hub基类的新实例"
        /// <summary>
        /// 初始化一个支持强类型的SignalRHub基类 <see cref="HubBase{T}"/> 的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        /// <param name="eventBus">事件总线接口</param>
        /// <param name="userCache">SignalR连接用户缓存接口</param>
        protected HubBase(IServiceProvider provider, IEventBus eventBus, IConnectionUserCache userCache)
        {
            ServiceProvider = provider;
            Logger = provider.GetLogger<HubBase<T>>();
            EventBus = eventBus;
            UserCache = userCache;
        }
        #endregion

        #endregion

        #region "方法"
        #region "在与集线器建立新连接时调用"
        /// <summary>
        /// 在与集线器建立新连接时调用
        /// </summary>
        /// <returns>一个<see cref="Task" />表示异步连接的</returns>
        public override async Task OnConnectedAsync()
        {
            HubConnectionEventData<T> eventData = new(Clients, Context, Groups);

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.AddConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }

            await base.OnConnectedAsync();

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogDebug("用户 {userKey}[{connectionId}] 与SignalR强类型集线器建立连接", userKey, Context.ConnectionId);
        }
        #endregion
        #region "当终止与集线器的连接时调用"
        /// <summary>
        /// 当终止与集线器的连接时调用
        /// </summary>
        /// <returns>一个<see cref="Task" />表示异步连接的</returns>
        public override async Task OnDisconnectedAsync(System.Exception exception)
        {
            HubDisconnectionEventData<T> eventData = new(Clients, Context, Groups);

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.RemoveConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }
            eventData.UserKey = userKey;
            UserCache.RemoveUserGroupByConnection(Context.ConnectionId);

            await base.OnDisconnectedAsync(exception);

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogDebug("用户 {userKey}[{connectionId}] 与SignalR强类型集线器终止连接", userKey, Context.ConnectionId);
        }
        #endregion

        //#region "加入组"
        ///// <summary>
        ///// 加入组
        ///// </summary>
        ///// <param name="groupKeys">组标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> AddToGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubAddToGroupEventData<T> eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (string groupKey in groupKeys)
        //    {
        //        await Groups.AddToGroupAsync(Context.ConnectionId, groupKey);
        //        UserCache.AddUserGroup(userKey, groupKey, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR强类型集线器加入组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion
        //#region "离开组"
        ///// <summary>
        ///// 离开组
        ///// </summary>
        ///// <param name="groupKeys">组标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> RemoveFromGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubRemoveFromGroupEventData<T> eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (string groupName in groupKeys)
        //    {
        //        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
        //        UserCache.RemoveUserGroup(userKey, groupName, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR强类型集线器离开组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion

        #endregion

        #region "受保护方法"
        #region "获取当前用户标识"
        /// <summary>
        /// 获取当前用户标识
        /// </summary>
        /// <returns></returns>
        protected string GetCurrentUserKey()
        {
            //获取用户Id信息
            string userKey = Context.User.Identity.GetUserId();
            userKey = userKey.IsMissing() ? KeyConstants.AnonymousUser : userKey;
            return userKey;
        }
        #endregion

        #endregion

    }
    #endregion

    /* 支持强类型的SignalR Hub基类
    #region "支持强类型的SignalR Hub基类"
    /// <summary>
    /// 支持强类型的SignalR Hub基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class HubBase<T> : HubBase where T : class
    {
        //字段
        private IHubCallerClients<T> _clients;

        #region "属性"
        #region "获取或设置 可用于调用连接到此集线器的客户端上的方法的强类型"
        /// <summary>
        /// 获取或设置 可用于调用连接到此集线器的客户端上的方法的<typeparamref name="T" />
        /// Gets or sets a <typeparamref name="T" /> that can be used to invoke methods on the clients connected to this hub
        /// </summary>
        public new IHubCallerClients<T> Clients
        {
            get
            {
                if (this._clients == null)
                    this._clients = (IHubCallerClients<T>)new TypedHubClients<T>(base.Clients);
                return this._clients;
            }
            set
            {
                this._clients = value;
            }
        }
        #endregion

        #endregion

        #region "构造函数"
        #region "初始化一个支持强类型的SignalRHub基类的新实例"
        /// <summary>
        /// 初始化一个支持强类型的SignalRHub基类 <see cref="SignalRHubBase{T}"/> 的新实例
        /// </summary>
        /// <param name="userCache">SignalR连接用户缓存接口</param>
        protected HubBase(IConnectionUserCache userCache)
            : base(userCache)
        { }
        #endregion

        #endregion

    }
    #endregion
    */

    #region "支持运行时解析类型的SignalR Hub基类"
    /// <summary>
    /// 支持运行时解析类型的SignalR Hub基类
    /// </summary>
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public abstract class DynamicHubBase : DynamicHub
    {
        #region "属性"
        #region "获取 服务提供者"
        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }
        #endregion
        #region "获取 日志记录器"
        /// <summary>
        /// 获取 日志记录器
        /// </summary>
        protected ILogger Logger { get; }
        #endregion
        #region "获取 通信连接用户缓存"
        /// <summary>
        /// 获取 通信连接用户缓存
        /// </summary>
        protected IConnectionUserCache UserCache { get; }
        #endregion
        #region "获取 事件总线"
        /// <summary>
        /// 获取 事件总线
        /// </summary>
        protected IEventBus EventBus { get; }
        #endregion

        #endregion

        #region "构造函数"
        #region "初始化一个支持运行时解析类型的SignalR Hub基类的新实例"
        /// <summary>
        /// 初始化一个支持运行时解析类型的SignalR Hub基类 <see cref="DynamicHubBase"/> 的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        /// <param name="eventBus">事件总线接口</param>
        /// <param name="userCache">SignalR连接用户缓存接口</param>
        protected DynamicHubBase(IServiceProvider provider, IEventBus eventBus, IConnectionUserCache userCache)
        {
            ServiceProvider = provider;
            Logger = provider.GetLogger<DynamicHubBase>();
            EventBus = eventBus;
            UserCache = userCache;
        }
        #endregion

        #endregion

        #region "方法"
        #region "在与集线器建立新连接时调用"
        /// <summary>
        /// 在与集线器建立新连接时调用
        /// </summary>
        /// <returns>一个<see cref="Task" />表示异步连接的</returns>
        public override async Task OnConnectedAsync()
        {
            HubConnectionDynamicEventData eventData = new(Clients, Context, Groups);

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.AddConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }

            await base.OnConnectedAsync();

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogDebug("用户 {userKey}[{connectionId}] 与SignalR运行时解析集线器建立连接", userKey, Context.ConnectionId);
        }
        #endregion
        #region "当终止与集线器的连接时调用"
        /// <summary>
        /// 当终止与集线器的连接时调用
        /// </summary>
        /// <returns>一个<see cref="Task" />表示异步连接的</returns>
        public override async Task OnDisconnectedAsync(System.Exception exception)
        {
            HubDisconnectionDynamicEventData eventData = new(Clients, Context, Groups);

            //获取当前用户标识
            string userKey = GetCurrentUserKey();
            if (!userKey.IsMissing())
            {
                var user = await UserCache.RemoveConnectionId(userKey, Context.ConnectionId);
                eventData.User = user;
            }
            eventData.UserKey = userKey;
            UserCache.RemoveUserGroupByConnection(Context.ConnectionId);

            await base.OnDisconnectedAsync(exception);

            //触发事件
            await EventBus?.PublishAsync(eventData);

            Logger.LogDebug("用户 {userKey}[{connectionId}] 与SignalR运行时解析集线器终止连接", userKey, Context.ConnectionId);
        }
        #endregion

        //#region "加入组"
        ///// <summary>
        ///// 加入组
        ///// </summary>
        ///// <param name="groupKeys">组标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> AddToGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubAddToGroupDynamicEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (string groupKey in groupKeys)
        //    {
        //        await Groups.AddToGroupAsync(Context.ConnectionId, groupKey);
        //        UserCache.AddUserGroup(userKey, groupKey, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR运行时解析集线器加入组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion
        //#region "离开组"
        ///// <summary>
        ///// 离开组
        ///// </summary>
        ///// <param name="groupKeys">组键标识集合</param>
        ///// <returns></returns>
        //public virtual async Task<AjaxResult> RemoveFromGroup(params string[] groupKeys)
        //{
        //    Check.NotNull(groupKeys, nameof(groupKeys));
        //    if (groupKeys?.Length <= 0)
        //    {
        //        return new AjaxResult("组集合不能为空", AjaxResultType.Error);
        //    }
        //    if (groupKeys.ToList().Exists(m => m.IsMissing()))
        //    {
        //        return new AjaxResult("组集合中组名不能为空", AjaxResultType.Error);
        //    }

        //    HubRemoveFromGroupDynamicEventData eventData = new(Clients, Context, Groups);

        //    //获取当前用户标识
        //    string userKey = GetCurrentUserKey();
        //    if (!userKey.IsMissing())
        //    {
        //        var user = await UserCache.GetUser(userKey);
        //        eventData.User = user;
        //    }

        //    foreach (string groupKey in groupKeys)
        //    {
        //        await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupKey);
        //        UserCache.RemoveUserGroup(userKey, groupKey, Context.ConnectionId);
        //    }

        //    eventData.GroupKeys = groupKeys;
        //    eventData.ConnectionId = Context.ConnectionId;
        //    //触发事件
        //    await EventBus?.PublishAsync(eventData);

        //    var msgString = $"用户：{userKey}[{Context.ConnectionId}] 通过SignalR运行时解析集线器离开组：{groupKeys.ExpandAndToString()}。";
        //    Logger.LogInformation(msgString);
        //    return new AjaxResult(msgString, AjaxResultType.Success);
        //}
        //#endregion

        #endregion

        #region "受保护方法"
        #region "获取当前用户标识"
        /// <summary>
        /// 获取当前用户标识
        /// </summary>
        /// <returns></returns>
        protected string GetCurrentUserKey()
        {
            //获取用户Id信息
            string userKey = Context.User.Identity.GetUserId();
            userKey = userKey.IsMissing() ? KeyConstants.AnonymousUser : userKey;
            return userKey;
        }
        #endregion

        #endregion

    }
    #endregion

}
